﻿#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define N 600//максимальный размер строки, считываемой из лог-файла
struct ip//структура определяет формат типа Х.Х.Х.Х, используемый для представления IP-адреса или маски подсети.Каждый элемент Х-целое число в диапазоне от 0 до 255.
{
	short x1,x2,x3,x4;
}maska,adress;//глобально объявляем структуры,которые впоследствии будут хранить сведения об исходной маске подсети и номере сети(ранге)
//Функция для преобразования описания маски в виде десятичного числа в соответствующее типа Х.Х.Х.Х
//В качестве формальных параметров по ссылке передаются десятичное значение маски и каждый из элементов структуры ip, описывающей маску
//Алгоритм: заполняем соответствующие биты в каждом поле единицами, начиная с большего, до тех пор, пока значение маски не станет равно 0.
int make(short *mask,short *cur)
{
    short q=128;
	while(q>=1)
		if(*mask>0)//если десятичное значение маски подсети больше 0
		{
			*cur=*cur+q;//формируем соответствующий бит в поле
			q=q/2;
			*mask=*mask-1;//декрементируем значение маски подсети
		}
		else
			return 0;
}
//Функция формирует значения исходных данных из файла : по заданному в файле CIDR определяет маску и номер сети (ранг?) в формате Х.Х.Х.Х.
int getadress(char *resultfilename)//Входной параметр - путь к файлу с описанием CIDR(диапазонов адресов)
{
	char *curst= malloc(10*sizeof(char));char st[50];
	short m;
	struct ip curip;
	FILE *f;
	if((f=fopen(resultfilename,"r"))==NULL)
	{
		printf("Result file not opened");
		exit(1);
	}
	fscanf(f,"%s",st);//считываем строку с описанием CIDR
	curst=strtok(st,"./");//выделяем в st подстроку,ограниченную знаками "/" и ".", то есть первый элемент данных типа Х.Х.Х.Х
	curip.x1=atoi(curst);//сохраняем это значение в объекте curip 
	curst=strtok(NULL,"./");
	curip.x2=atoi(curst);
	curst=strtok(NULL,"./");
	curip.x3=atoi(curst);
	curst=strtok(NULL,"./");
	curip.x4=atoi(curst);
	curst=strtok(NULL,"./");
	m=atoi(curst);//получаем числовое значение маски подсети
	make(&m,&maska.x1);//формируем значения маски подсети - первое поле структуры
	make(&m,&maska.x2);//формируем значения маски подсети - второе поле структуры
	make(&m,&maska.x3);//формируем значения маски подсети - 3 поле структуры
	make(&m,&maska.x4);//формируем значения маски подсети - 4 поле структуры
	adress.x1=curip.x1&maska.x1;//вычисляем номер сети( ранг или адрес(здесь)): каждое поле соответствующих структур (заданного ip адреса и маски подсети) умножаем логически 
	adress.x2=curip.x2&maska.x2;
	adress.x3=curip.x3&maska.x3;
	adress.x4=curip.x4&maska.x4;
	fclose(f);
	return 0;
}
//функия просматривает каждую строку лог файла и, если номер этой сети( ранг ?) совпадает с возвращенным функцией getadress(),
//то прибавляет к общему количеству отданной информации то, которое соответствует текущему ip-адресу
//входные параметры- аргументы функции main: путь к логфайлу и путь к файлу с исходными данными о диапазоне
//возвращает общее количество переданной инф-ии в байтах для одного адреса из диапазона
int size(char *logfilename,char *resultfilename)
{
	int sum=0;//перемення для хранения суммы переданного количества информации
	struct ip curip;//создание объекта типа ip для хранения промежуточных значений ip-адреса,считываемых из лог файла
	char str[N],str1[N];
	char *cur= malloc(sizeof(int));
	char *curword= malloc(50*sizeof(char));
	FILE *log;
	if((log=fopen(logfilename,"r"))==NULL)//открываем лог файл для чтения
	{
		printf("Log1 file not opened");
		exit(0);
	}
	getadress(resultfilename);//функция вычисляет адрес и маску сети, по которым будет осуществляться поиск среди ip-адресов логфайла
	while(!feof(log))//выполнять пока не достигнут конец файла
	{
		fgets(str1,N,log);//считываем строку в str1
		strcpy(str,str1);//сохраняем копию считанной строки в str
		cur=strtok(str1," .");//выделяем в str подстроку,ограниченную знаками " " и ".", то есть первый элемент данных типа Х.Х.Х.Х
		curip.x1=atoi(cur);//сохраняем это значение в объекте curip
		cur=strtok(NULL," .");//выделяем в str подстроку,ограниченную знаками " " и ".", то есть второй элемент данных типа Х.Х.Х.Х
		curip.x2=atoi(cur);
		cur=strtok(NULL," .");//выделяем в str подстроку,ограниченную знаками " " и ".", то есть третий элемент данных типа Х.Х.Х.Х
		curip.x3=atoi(cur);
		cur=strtok(NULL," .");//выделяем в str подстроку,ограниченную знаками " " и ".", то есть четвертый элемент данных типа Х.Х.Х.Х
		curip.x4=atoi(cur);//сохраняем это значение в объекте curip
		if(((curip.x1&maska.x1)==adress.x1)&&((curip.x2&maska.x2)==adress.x2))//сравниваем ранг сети для текущего ip-адреса лог файла с заданными
			if(((curip.x3&maska.x3)==adress.x3)&&((curip.x4&maska.x4)==adress.x4))
			{
				curword=strchr(str,'"');//ищем в строке лог файла символ """( функция возвратит указатель на строку,начинающуюся с этого символа)
				curword=curword+1;//увеличиваем указатель на 1(переходим через найденный символ)
				curword=strchr(curword,'"');//ищем второй символ """
				curword=curword+1;//увеличиваем указатель на 1(переходим через найденный символ)
				strcpy(str,curword);//копируем полученную строку
				curword=strtok(str," ");//ищем в строке str подстроки, разделенные пробелами
				curword=strtok(NULL," ");//ищем в строке str подстроки, разделенные пробелами; полученная строка - искомое количество переданной информации
				sum=sum+atoi(curword);//прибавляем к суммарному количеству переданной информации текущее
			}
	}
	return sum;
	fclose(log);
}
void printfile(int result,char *resultfilename)//вывод количества информации в файл - пока в тот же,где задан диапазон 
{
	FILE *f;
	if((f=fopen(resultfilename,"a"))==NULL)//открываем файл для дозаписи в конец
	{
		printf("Result file not opened");
		exit(1);
	}
	else
	{
		fprintf(f,"\n%s%d%s\t\t\t%0.6f%s","Общий объем отданной информации:\n",result,"б",((float) result/1048576) , "Мб");//выводим результат в байтах и мегабайтах
	}
	fclose(f);
}
void main(int argc,char *argv[])//в качестве аргументов задаются сначала путь к лог файлу затем путь к файлу,хранящему результат
{
	int result;//переменная, содержащая результат: количество информации для одного адреса из диапазона(пока только для одного)!!!!!!!!!!!!!!!!!!!!!!
	if(argc<3){//если аргументов у функции main меньше 3 - то есть не заданы 2 пути к файлам
		printf("There's no file path");
		return;
	}
	result=size(argv[1],argv[2]);//вызываем функцию вычисления количество информации
	printfile(result,argv[2]);//выводим значение результата в файл
}